﻿//===============================================================================
// Microsoft patterns & practices Enterprise Library
// Exception Handling Application Block
//===============================================================================
// Copyright © Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.ComponentModel;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration;

namespace EntLibContrib.ExceptionHandling.Configuration
{
    /// <summary>
    /// Represents the configuration data for a <see cref="WrapHandler"/>.
    /// </summary>	
    [Assembler(typeof(SqlExceptionWrapHandlerAssembler))]
    public class SqlExceptionWrapHandlerData : ExceptionHandlerData
    {
        private static AssemblyQualifiedTypeNameConverter typeConverter = new AssemblyQualifiedTypeNameConverter();

        private const string errorCodesProperty = "errorCodes";
        private const string exceptionMessageProperty = "defaultExceptionMessage";
        private const string wrapExceptionTypeProperty = "defaultWrapExceptionType";

        public SqlExceptionWrapHandlerData()
        {
        }

        public SqlExceptionWrapHandlerData(string name, ErrorCodeNotConfiguredBehavior errorCodeNotConfiguredBehavior, string defaultExceptionMessage, string defaultWrapExceptionTypeName, NamedElementCollection<ErrorCodeEntryData> errorCodes)
            : base(name, typeof(SqlExceptionWrapHandler))
        {
            this.ErrorCodeNotConfiguredBehavior = errorCodeNotConfiguredBehavior;
            this.DefaultExceptionMessage = defaultExceptionMessage;
            this.DefaultWrapExceptionTypeName = defaultWrapExceptionTypeName;
            this.ErrorCodes = errorCodes;
        }

        [ConfigurationProperty(exceptionMessageProperty, IsRequired = false)]
        public string DefaultExceptionMessage
        {
            get { return (string)this[exceptionMessageProperty]; }
            set { this[exceptionMessageProperty] = value; }
        }


        /// <summary>
        /// Gets or sets the type of the replacement exception.
        /// </summary>
        public Type DefaultWrapExceptionType
        {
            get { return (Type)typeConverter.ConvertFrom(DefaultWrapExceptionTypeName); }
            set { DefaultWrapExceptionTypeName = typeConverter.ConvertToString(value); }
        }

        /// <summary>
        /// Gets or sets the fully qualified type name of the replacement exception.
        /// </summary>
        /// <value>
        /// The fully qualified type name of the replacement exception.
        /// </value>
        [ConfigurationProperty(wrapExceptionTypeProperty, IsRequired = true)]
        public string DefaultWrapExceptionTypeName
        {
            get { return (string)this[wrapExceptionTypeProperty]; }
            set { this[wrapExceptionTypeProperty] = value; }
        }

        [ConfigurationProperty(errorCodesProperty)]
        public NamedElementCollection<ErrorCodeEntryData> ErrorCodes
        {
            get
            {
                return (NamedElementCollection<ErrorCodeEntryData>)base[errorCodesProperty];
            }

            private set
            {
                base[errorCodesProperty] = value;
            }
        }

        private const string errorCodeNotConfiguredBehaviorPropertyName = "errorCodeNotConfiguredBehavior";
        [ConfigurationProperty(errorCodeNotConfiguredBehaviorPropertyName)]
        public ErrorCodeNotConfiguredBehavior ErrorCodeNotConfiguredBehavior
        {
            get { return (ErrorCodeNotConfiguredBehavior)this[errorCodeNotConfiguredBehaviorPropertyName]; }
            set { this[errorCodeNotConfiguredBehaviorPropertyName] = value; }
        }
    }

    /// <summary>
    /// This type supports the Enterprise Library infrastructure and is not intended to be used directly from your code.
    /// Represents the process to build a <see cref="WrapHandler"/> described by a <see cref="WrapHandlerData"/> configuration object.
    /// </summary>
    /// <remarks>This type is linked to the <see cref="WrapHandlerData"/> type and it is used by the <see cref="ExceptionHandlerCustomFactory"/> 
    /// to build the specific <see cref="IExceptionHandler"/> object represented by the configuration object.
    /// </remarks>
    public class SqlExceptionWrapHandlerAssembler : IAssembler<IExceptionHandler, ExceptionHandlerData>
    {
        /// <summary>
        /// This method supports the Enterprise Library infrastructure and is not intended to be used directly from your code.
        /// Builds a <see cref="WrapHandler"/> based on an instance of <see cref="WrapHandlerData"/>.
        /// </summary>
        /// <seealso cref="ExceptionHandlerCustomFactory"/>
        /// <param name="context">The <see cref="IBuilderContext"/> that represents the current building process.</param>
        /// <param name="objectConfiguration">The configuration object that describes the object to build. Must be an instance of <see cref="WrapHandlerData"/>.</param>
        /// <param name="configurationSource">The source for configuration objects.</param>
        /// <param name="reflectionCache">The cache to use retrieving reflection information.</param>
        /// <returns>A fully initialized instance of <see cref="WrapHandler"/>.</returns>
        public IExceptionHandler Assemble(IBuilderContext context, ExceptionHandlerData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)
        {
            SqlExceptionWrapHandlerData castedObjectConfiguration
                = (SqlExceptionWrapHandlerData)objectConfiguration;

            return new SqlExceptionWrapHandler(castedObjectConfiguration);
        }
    }

    public enum ErrorCodeNotConfiguredBehavior
    {
        WrapWithDefaultException,
        ReturnOriginalException
    }
}